home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Games Extra 1996 June
/
Amiga Games Extra 1996 #6.iso
/
userbox
/
publicdomain
/
cuckoo
/
source
/
playsound.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-06
|
6KB
|
218 lines
/*****************************************************************************
* PlaySound.c
* This routine sets up an ioRequest and plays back a waveform through the
* Amiga audio hardware
*
* Usage : PlaySound(buffer,repeat,period,volume)
* buffer is a pointer to a waveform
* repeat is the number of times to play the wave (0 == forever)
* period determines the playback rate (minimum value == 124)
* volume goes from 0 to 64
*****************************************************************************/
#include "exec/types.h"
#include "devices/audio.h"
#include "exec/memory.h"
#define LEFT0F 1
#define RIGHT0F 2
#define RIGHT1F 4
#define LEFT1F 8
#define SIGBREAKF_CTRL_C (1<<12)
extern struct MsgPort *CreatePort();
struct IOAudio *AllocMem();
/* Look for a left channel, then a right */
UBYTE allocationMap[] = { LEFT0F, LEFT1F, RIGHT0F, RIGHT1F };
/*****************************************************************************
* Purpose: To allocate and initialize an IO Request Block. *
*****************************************************************************/
SetIOA(per, vol, repeat, len, ioa)
LONG per, vol, repeat;
ULONG len;
struct IOAudio **ioa;
{
struct MsgPort *port;
/* Allocate IOAudio structure */
(*ioa) = AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
/* If Allocation Successful ... */
if (*ioa)
{
/* Set Priority */
(*ioa)->ioa_Request.io_Message.mn_Node.ln_Pri = 10;
/* Create Message port for IORequest to talk to Amiga */
if (!(port = CreatePort(NULL, 0)))
{
FreeMem((*ioa), sizeof(struct IOAudio));
*ioa = NULL;
}
/* If Creation Successful ... */
else
{
/* Get a channel */
(*ioa)->ioa_Request.io_Message.mn_ReplyPort = port;
(*ioa)->ioa_Data = allocationMap;
(*ioa)->ioa_Length = sizeof(allocationMap);
/* Open Audio Device for output */
if(OpenDevice(AUDIONAME, 0, (*ioa), 0))
{
DeletePort(port);
FreeMem((*ioa), sizeof(struct IOAudio));
*ioa = NULL;
}
/* If open worked ... */
else
{
/* Set Up Request */
(*ioa)->ioa_Request.io_Flags = ADIOF_PERVOL;
(*ioa)->ioa_Request.io_Command = CMD_WRITE;
(*ioa)->ioa_Period = per;
(*ioa)->ioa_Volume = vol;
/* For some reason, the Audio chip can't play samples */
/* longer than 131k, so we kludge. Oh, well. */
if(len < 131000)
(*ioa)->ioa_Cycles = repeat;
else
(*ioa)->ioa_Cycles = 1;
}
}
}
}
/*****************************************************************************
* Purpose: To play back a sound. *
*****************************************************************************/
struct IOAudio *PlaySound(buffer, buflen, repeat, period, volume)
BYTE *buffer;
ULONG buflen;
LONG repeat,period,volume;
{
struct IOAudio *ioa;
BYTE *DataPtr;
ULONG PlayLen;
DataPtr = buffer;
/* Set Up IOAudio structure */
SetIOA(period, volume, repeat, buflen, &ioa);
if (!ioa)
return(NULL);
/* Set up data and length pointers of ioa */
SetLength(&PlayLen, buflen, &DataPtr, ioa);
/* Send command to Audio chip */
BeginIO(ioa);
repeat--;
/* If no data remains to play, return ioa pointer */
if(PlayLen == 0)
return(ioa);
/* If there is more (buflen > 131000), continue until there isn't */
while(TRUE)
{
ULONG signals;
/* Wait until current chunk is done */
signals = Wait((1 << ioa->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) | SIGBREAKF_CTRL_C);
if (signals & SIGBREAKF_CTRL_C)
{
SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
return(ioa);
}
/* If more remains, continue */
if(PlayLen > 0)
{
/* update pointers and start next chunk */
FixLength(&PlayLen, &DataPtr, ioa);
BeginIO(ioa);
/* return if playing the last chunk for the last time */
if((PlayLen == 0) && (repeat == 0))
return(ioa);
}
/* If not ... */
else
{
/* Check repeat counter */
if(repeat != 0)
{
/* Restart wave */
DataPtr = buffer;
SetLength(&PlayLen, buflen, &DataPtr, ioa);
BeginIO(ioa);
if(repeat > 0)
repeat--;
}
}
}
}
/*****************************************************************************
* Purpose: To stop and delete a sound. THIS IS THE CLEAN UP ROUTINE!! *
*****************************************************************************/
StopSound(struct IOAudio *ioa)
{
AbortIO(ioa);
if(ioa->ioa_Request.io_Device)
CloseDevice(ioa);
if(ioa->ioa_Request.io_Message.mn_ReplyPort)
DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
if(ioa)
FreeMem(ioa,sizeof(struct IOAudio));
}
/*****************************************************************************
* Purpose: To set the length of the sound to be played. *
*****************************************************************************/
SetLength(ULONG *LenPtr, ULONG buflen, BYTE **DataHndl, struct IOAudio *ioa)
{
if(buflen <= 131000)
(*LenPtr) = buflen;
else
(*LenPtr) = 131000;
ioa->ioa_Length = (*LenPtr);
ioa->ioa_Data = (*DataHndl);
if((*LenPtr) != buflen)
{
(*LenPtr) = buflen - 131000;
(*DataHndl) += 131000;
}
else
(*LenPtr) = 0;
}
/*****************************************************************************
* Purpose: To Check, if the full sound is to be played (or max 131000 bytes)*
*****************************************************************************/
FixLength(ULONG *LenPtr, BYTE **DataHndl, struct IOAudio *ioa)
{
if((*LenPtr) > 131000)
{
ioa->ioa_Length = 131000;
ioa->ioa_Data = (*DataHndl);
(*LenPtr) -= 131000;
(*DataHndl) += 131000;
}
else
{
ioa->ioa_Length = (*LenPtr);
ioa->ioa_Data = (*DataHndl);
(*LenPtr) = 0;
}
}